package frog.lazy.framework.http.aspect;

import cn.hutool.json.JSONUtil;
import frog.lazy.framework.core.tools.NetworkUtil;
import frog.lazy.framework.http.constant.SystemConstant;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;

/**
 * 切面日志
 */
@Slf4j
@Aspect
@Component
public class ControllerAspect {

    @Pointcut(value = "@within(org.springframework.web.bind.annotation.RestController)" )
    public void restful() {}

    @Pointcut(value = "@within(org.springframework.stereotype.Controller)")
    public void rest() {}

    @Before("restful()")
    public void doBefore(JoinPoint joinPoint) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        log.info("========================================== Request Start ==========================================");
        // 打印请求 标识
        log.info("URL tar        : {}", request.getAttribute(SystemConstant.SESSION_ID));
        // 请求 url
        log.info("URL            : {}", request.getRequestURL().toString());
        //  Http method
        log.info("HTTP Method    : {}", request.getMethod());
        // 调用 controller 的全路径以及执行方法
        log.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        // 请求的 IP
        log.info("IP             : {}", NetworkUtil.getIpAddress(request));
        // 请求入参 TODO 缺少文件流的过虑
        log.info("Request Args   : {}", JSONUtil.toJsonStr(joinPoint.getArgs()));
        log.info("========================================== Request End   ===========================================");
    }


    @SneakyThrows
    @AfterReturning(value = "restful()", returning = "result")
    public void doAfterReturning(JoinPoint JoinPoint, Object result) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        log.info("========================================== Response Start ==========================================");
        log.info("URL tar        : {}", request.getAttribute(SystemConstant.SESSION_ID));
        // 请求响应
        log.info("Response Data  : {}", Optional.ofNullable(result).isPresent() ? JSONUtil.toJsonStr(result):null);
        // 请求耗时
        log.info("Time-Consuming : {}ms", System.currentTimeMillis() - (long)request.getAttribute(SystemConstant.START_TIME));
        log.info("========================================== Response End   ==========================================");
    }
}
